/**
 * Copyright 2000 self.com.au
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. (http://www.apache.org/licenses/LICENSE-2.0)
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
 * the specific language governing permissions and limitations under the License.
 *
 * <dhamma-message src="Atisha (11th century Tibetan Buddhist master)">
 * 	The greatest achievement is selflessness. The greatest worth is self-mastery.
 * 	The greatest quality is seeking to serve others. The greatest precept is continual awareness.
 * 	The greatest medicine is the emptiness of everything. The greatest action is not conforming with the worlds ways.
 * 	The greatest magic is transmuting the passions. The greatest generosity is non-attachment.
 * 	The greatest goodness is a peaceful mind. The greatest patience is humility.
 * 	The greatest effort is not concerned with results. The greatest meditation is a mind that lets go.
 * 	The greatest wisdom is seeing through appearances. 
 * </dhamma-message>
 *
 * @author Ashin Wimalajeewa
 */
package self.amigo.elem.bpm;

import java.awt.*;
import java.util.*;

import org.w3c.dom.*;

import self.awt.*;
import self.gee.*;
import self.lang.*;

import self.amigo.elem.*;
import self.amigo.elem.uml.*;

public class StageView extends ARectangularLinkable {
	
	/**
	 * If the internal state of this class ever changes in such a way that it can't be defaulted,
	 * then the {@link #serialVersionUID} should be incremented to ensure serialized instances cleanly fail.  
	 */
	private static final long serialVersionUID = 1;
	
  final static public String NAMECOMPARTMENT_PROP = "NameCompartment";
  final static public String FILL_PROP = "Fill";
  final static public String FILL_COMPARTMENT = "CompartmentColor";
  final static public String FILL_BACKGROUND1 = "BackgroundGradColor1";
  final static public String FILL_BACKGROUND2 = "BackgroundGradColor2";

  public StageView() {
    delegate =  new Essential();
    setDelegate( delegate );
  }

  private class Essential extends ARectangularHandledElement {
  	
	/**
	 * If the internal state of this class ever changes in such a way that it can't be defaulted,
	 * then the {@link #serialVersionUID} should be incremented to ensure serialized instances cleanly fail.  
	 */
	private static final long serialVersionUID = 1;
	
    transient private PaintContext context = new PaintContext();

    protected NameCompartmentFeature      nameCompartment = new NameCompartmentFeature();
    private FillableFeature  fillData = new FillableFeature();
    private FillableFeature  fillBackgroundGrad1 = new FillableFeature( "backgroundgradcolor1" );
    private FillableFeature  fillBackgroundGrad2 = new FillableFeature( "backgroundgradcolor2" );
    private FillableFeature  fillCompartment = new FillableFeature( "compartmentcolor" );
    protected MultiCompartmentPainter   compartmentPainter;

    private String[]                    compAuxViews = new String[0];
    private boolean[]                   compAuxViewsVis = new boolean[0];

    public Essential() {
      fig.setBounds( 10, 10, 95, 326 ); // 40
      fillData.fillColor = Color.white;
      fillCompartment.fillColor = new Color( 159, 203, 169 );
      fillBackgroundGrad1.fillColor = new Color( 51, 51, 153 );
      fillBackgroundGrad2.fillColor = null; // new Color( 219, 219, 220 );
      resetFrame();
    }

    public void       setLayer( IDiagramLayer layerToDrawOn, boolean add ) {
      super.setLayer( layerToDrawOn, add );
      compartmentPainter = (MultiCompartmentPainter) PainterManager.getPainterForOwner(
                                          layer, MultiCompartmentPainter.class );
    }

    public void       move( Dimension moveBy, java.awt.event.MouseEvent e, int dragState ) {
      super.move( moveBy, e, dragState );
      if ( dragState == self.gee.IGraphicElement.DS_AFTER_LAST ) {
        initHandlePoints();
      }
    }

//    public void       resize( int x, int y, Point[] handle, java.awt.event.MouseEvent e, int dragState ) {
//      super.resize( x, y, handle, e, dragState );
//      if ( dragState == self.gee.IGraphicElement.DS_AFTER_LAST ) {
//        initHandlePoints();
//      }
//    }
    public void       resize( int x, int y, Point[] handle, java.awt.event.MouseEvent e, int dragState ) {
      if ( dragState == self.gee.IGraphicElement.DS_AFTER_LAST ) {
        super.resize( x, y, handle, e, dragState );
        return;
      }
      layer.beginUpdate();
      super.resize( x, y, handle, e, dragState );
      if ( fig.width < 95 )
        fig.width = 95;
      if ( fig.height < 40 )
        fig.height = 40;
      resetFrame();
      layer.endUpdate();
    }

    protected void resetFrame() {
      context.setBounds();
    }

    public void       paint( Graphics surface ) {
      String symbol = nameCompartment.aidLink;
      boolean paintSymbol = !StringUtils.isNullOrEmpty( symbol );
      if ( !outlineOnly && paintSymbol )
        SymbolPaintManagerUtils.startSymbol( surface, this, symbol );
      try {
        paintBackground( surface );
        paintShevron( surface );
        paintCompartment( surface );
      } finally {
        if ( !outlineOnly && paintSymbol )
          SymbolPaintManagerUtils.endSymbol( surface );
      }
      compartmentPainter.paint( surface, context, outlineOnly );
    }

    private void paintBackground( Graphics surface ) {
      if (!outlineOnly && (fillBackgroundGrad1.fillColor != null) ) {
        if ( fillBackgroundGrad2.fillColor != null ) {
          int middle = fig.y + (fig.height/2);
          GradientPaint gp = new GradientPaint( fig.x, middle, fillBackgroundGrad1.fillColor, fig.x+fig.width, middle, fillBackgroundGrad2.fillColor, true );
          Paint p = ((Graphics2D) surface).getPaint();
          try {
            ((Graphics2D) surface).setPaint( gp );
            surface.fillRect( fig.x, fig.y, fig.width, fig.height );
          } finally {
            ((Graphics2D) surface).setPaint( p );
          }
        } else {
          surface.setColor( fillBackgroundGrad1.fillColor );
          surface.fillRect( fig.x, fig.y, fig.width, fig.height );
        }
      }
      surface.setColor( frameColor );
      surface.drawRect( fig.x, fig.y, fig.width, fig.height );
    }

    private void paintShevron( Graphics surface ) {
      int[] xcoords = new int[5];
      int[] ycoords = new int[5];
      xcoords[0] = fig.x + 5;                   // TL
      ycoords[0] = fig.y + 5;
      xcoords[1] = fig.x + fig.width -5 -22;    // TR
      ycoords[1] = ycoords[0];
      xcoords[2] = xcoords[1] + 22;             // MR
      ycoords[2] = ycoords[1] + 16 ;
      xcoords[3] = xcoords[1] ;
      ycoords[3] = ycoords[2] + 16 ;
      xcoords[4] = xcoords[0];
      ycoords[4] = ycoords[3];

      if ( !outlineOnly ) {
        if (fillData.fillColor != null) {
          surface.setColor(fillData.fillColor);
          surface.fillPolygon( xcoords, ycoords, xcoords.length );
        }
      }
      surface.setColor(frameColor);
      surface.drawPolygon( xcoords, ycoords, xcoords.length );
    }

    private void paintCompartment( Graphics surface ) {
      int yPos = fig.y + 42;
      int yEnd = fig.y + fig.height;
      if ( !outlineOnly ) {
        if (fillCompartment.fillColor != null) {
          if ( yPos + 5 < yEnd ) {
            surface.setColor(fillCompartment.fillColor);
            surface.fillRect( fig.x + 5, yPos, fig.width - 10, yEnd - yPos - 5 );
          }
        }
      }
      surface.setColor(frameColor);
      surface.drawRect( fig.x + 5, yPos, fig.width - 10, yEnd - yPos - 5 );
    }

    // IEditableElement support
    public void       getProperties( Map store ) {
      store.put( NAMECOMPARTMENT_PROP, nameCompartment.clone() );
      store.put( FILL_PROP, fillData.clone() );
      store.put( FILL_COMPARTMENT, fillCompartment.clone() );
      store.put( FILL_BACKGROUND1, fillBackgroundGrad1.clone() );
      store.put( FILL_BACKGROUND2, fillBackgroundGrad2.clone() );
    }

    public void       setProperties( Map data ) {
      nameCompartment.set( (NameCompartmentFeature)data.get( NAMECOMPARTMENT_PROP) );
      fillData.set( (FillableFeature) data.get(FILL_PROP) );
      fillCompartment.set( (FillableFeature) data.get(FILL_COMPARTMENT) );
      fillBackgroundGrad1.set( (FillableFeature) data.get(FILL_BACKGROUND1) );
      fillBackgroundGrad2.set( (FillableFeature) data.get(FILL_BACKGROUND2) );
      layer.setDirty();
    }

    // IPersistentElement support
    public void readFrom( Node self, HashMap idObjLookUp ) throws DOMException {
      super.readFrom( self, idObjLookUp );
      nameCompartment.readFrom( self, idObjLookUp );
      fillData.readFrom( self, idObjLookUp );
      fillCompartment.readFrom( self, idObjLookUp );
      fillBackgroundGrad1.readFrom( self, idObjLookUp );
      fillBackgroundGrad2.readFrom( self, idObjLookUp );
    }

    public void writeTo( Document doc, Element self, HashMap objIdLookup ) throws DOMException {
      super.writeTo( doc, self, objIdLookup );
      nameCompartment.writeTo( doc, self, objIdLookup );
      fillData.writeTo( doc, self, objIdLookup );
      fillCompartment.writeTo( doc, self, objIdLookup );
      fillBackgroundGrad1.writeTo( doc, self, objIdLookup );
      fillBackgroundGrad2.writeTo( doc, self, objIdLookup );
    }

    class PaintContext implements ICompartmentsRenderInfo {
      private Rectangle textFig = new Rectangle();

      public void setBounds() {
        textFig.setBounds( fig.x + 6, fig.y + 6, fig.width -6 -22, 30 ); // 63
      }

      public Rectangle  getBounds() {
        return textFig;
      }

      public String     getName() {
        return nameCompartment.name;
      }

      public String     getSymbol() {
        return StringUtils.toNullOrNonEmptyValue( nameCompartment.aidLink );
      }

      public boolean    isNameUnderlined() {
        return false;
      }

      public boolean    isNameItalic() {
        return false;
      }

      public String     getStereoType() {
        return StringUtils.toNullOrNonEmptyValue( nameCompartment.stereotype );
      }

      public String     getNamespace() {
        return StringUtils.toNullOrNonEmptyValue( nameCompartment.nameSpace );
      }

      public boolean[] getVisibleAuxilaryCompartments() {
        return compAuxViewsVis;
      }

      public String[]  getAuxilaryCompartments() {
        return compAuxViews;
      }
    }

  }
}
